<!DOCTYPE html>
<!--
    Stub client that connects to an HITL server by IP address, sends the "client ready!" message, receives server messages, and displays the incoming message rate. It does not send client state or attempt to render received gfx-replay keyframes.
-->
<html>
<head>
    <title>WebSocket Client</title>
    <style>
        #status {
            font-weight: bold;
        }
        #keyframeCount {
            font-weight: bold;
        }
    </style>
</head>
<body>
    <table>
        <tr>
            <td>
                <label for="serverIp">Server IP:</label>
            </td>
            <td>
                <input type="text" id="serverIp" value="0.0.0.0" style="width: 500px">
            </td>
        </tr>
        <tr>
            <td>
                <label for="serverPort">Port:</label>
            </td>
            <td>
                <input type="text" id="serverPort" value="18000" style="width: 500px">
            </td>
        </tr>
    </table>
    <br>
    <button id="connectButton">Connect</button>
    <button id="disconnectButton" disabled>Disconnect</button>
    <hr>
    <div id="status">Disconnected</div>
    <div id="serverUrl">Server URL:</div>
    <div id="messageRate">Message Frequency (Hz): 0.0</div>
    <hr>
    <div id="keyframeCount">Keyframe Count: 0</div>
    <div id="loadCount">Load Count: 0</div>
    <div id="creationCount">Creation Count: 0</div>
    <div id="stateUpdateCount">Update Count: 0</div>
    <div id="deletionCount">Deletion Count: 0</div>
    <div id="rigCreationCount">Rig Creation Count: 0</div>
    <div id="rigUpdateCount">Rig Update Count: 0</div>
    <div id="messageCount">Message Count: 0</div>

    <script>
        class Stats {
            constructor() {
                this.keyframeCount = 0;
                this.loadCount = 0;
                this.creationCount = 0;
                this.stateUpdateCount = 0;
                this.deletionCount = 0;
                this.rigCreationCount = 0;
                this.rigUpdateCount = 0;
                this.messageCount = 0;
            }
        }

        var ws = null;
        var messageCount = 0;
        var stats = null;
        var lastUpdateTime = Date.now();

        function connect() {
            var ip = document.getElementById('serverIp').value;
            var port = document.getElementById('serverPort').value;
            var url = 'ws://' + ip + ':' + port;
            document.getElementById('serverUrl').textContent = 'Server URL: ' + url;
            ws = new WebSocket(url);
            var sendIntervalId = null;  // Variable to hold the ID of the interval
            var recentServerKeyframeId = null;

            ws.onopen = function() {
                document.getElementById('status').textContent = 'Connected';
                document.getElementById('connectButton').disabled = true;
                document.getElementById('disconnectButton').disabled = false;
                document.getElementById('serverIp').disabled = true;
                document.getElementById('serverPort').disabled = true;

                let connectionParams = {
                    isClientReady: true
                };
                var message = JSON.stringify(connectionParams);  // Convert the object to a JSON string
                ws.send(message);  // Send the JSON string

                stats = new Stats();

                // Start sending messages at 10 Hz
                sendIntervalId = setInterval(function() {
                    var dict = {};  // Create an empty JavaScript object

                    // Our stub client only sends recentServerKeyframeId. It doesn't send local GUI input or other client state.
                    if (recentServerKeyframeId != null) {
                        dict.recentServerKeyframeId = recentServerKeyframeId;
                    }
                    var message = JSON.stringify(dict);  // Convert the object to a JSON string
                    ws.send(message);  // Send the JSON string
                }, 100);  // Repeat every 100 milliseconds
            };

            ws.onclose = function() {
                document.getElementById('status').textContent = 'Disconnected';
                document.getElementById('connectButton').disabled = false;
                document.getElementById('disconnectButton').disabled = true;
                document.getElementById('serverIp').disabled = false;
                document.getElementById('serverPort').disabled = false;

                if (sendIntervalId) {
                    clearInterval(sendIntervalId);
                    sendIntervalId = null;
                }
                recentServerKeyframeId = null;
            };

            ws.onmessage = function() {
                messageCount++;

                var message = event.data;
                var dict = JSON.parse(message);

                // Update stats
                if ("keyframes" in dict) {
                    keyframes = dict["keyframes"]
                    if (keyframes.length) {
                        for (i = 0; i < keyframes.length; ++i)
                        {
                            stats.keyframeCount++;
                            document.getElementById('keyframeCount').textContent = 'Keyframe Count: ' + stats.keyframeCount;
                            keyframe = keyframes[i];
                            if ("loads" in keyframe) {
                                stats.loadCount += keyframe["loads"].length;
                                document.getElementById('loadCount').textContent = 'Load Count: ' + stats.loadCount;
                            }
                            if ("creations" in keyframe) {
                                stats.creationCount += keyframe["creations"].length;
                                document.getElementById('creationCount').textContent = 'Creation Count: ' + stats.creationCount;
                            }
                            if ("stateUpdates" in keyframe) {
                                stats.stateUpdateCount += keyframe["stateUpdates"].length;
                                document.getElementById('stateUpdateCount').textContent = 'Update Count: ' + stats.stateUpdateCount;
                            }
                            if ("deletions" in keyframe) {
                                stats.deletionCount += keyframe["deletions"].length;
                                document.getElementById('deletionCount').textContent = 'Deletion Count: ' + stats.deletionCount;
                            }
                            if ("rigCreations" in keyframe) {
                                stats.rigCreationCount += keyframe["rigCreations"].length;
                                document.getElementById('rigCreationCount').textContent = 'Rig Creation Count: ' + stats.rigCreationCount;
                            }
                            if ("rigUpdates" in keyframe) {
                                stats.rigUpdateCount += keyframe["rigUpdates"].length;
                                document.getElementById('rigUpdateCount').textContent = 'Rig Update Count: ' + stats.rigUpdateCount;
                            }
                            if ("message" in keyframe) {
                                stats.messageCount += Object.keys(keyframe["message"]).length;
                                document.getElementById('messageCount').textContent = 'Message Count: ' + stats.messageCount;
                            }
                        }

                        lastKeyframe = keyframes[keyframes.length - 1];
                        if ("message" in lastKeyframe) {
                            stats.messageCount++;
                            // Parse the latest serverKeyframeId from received keyframes
                            message = lastKeyframe["message"]
                            if ("serverKeyframeId" in message) {
                                recentServerKeyframeId = message["serverKeyframeId"];
                            }
                        }
                    }
                }
            };
        }

        function disconnect() {
            if (ws) {
                ws.close();
            }
        }

        function updateMessageRate() {
            var now = Date.now();
            var deltaTime = (now - lastUpdateTime) / 1000;  // Convert to seconds
            var messageRate = messageCount / deltaTime;
            document.getElementById('messageRate').textContent = 'Message Frequency (Hz): ' + messageRate.toFixed(1);
            messageCount = 0;
            lastUpdateTime = now;
        }

        document.getElementById('connectButton').addEventListener('click', connect);
        document.getElementById('disconnectButton').addEventListener('click', disconnect);
        setInterval(updateMessageRate, 2000);  // Update message rate every 2 seconds
    </script>
</body>
</html>
